package multi_thread.completable_future;

import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

public class Main {
    public static void main(String[] args) {

        //创建异步执行任务
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->fetchPrice("10000",""));


        cf.thenAccept((result)->{
            System.out.println("price: " + result);
        });

        //如果执行异常
        cf.exceptionally((e)->{
            e.printStackTrace();
            return null;
        });

        /**
         * 多个CompletableFuture可以串行执行，例如，定义两个CompletableFuture，第一个CompletableFuture根据证券名称查询证券代码，
         * 第二个CompletableFuture根据证券代码查询证券价格，这两个CompletableFuture实现串行操作如下：
         */

        CompletableFuture<String> cfQuery = CompletableFuture.supplyAsync(()-> queryCode("中国石油",""));

        CompletableFuture<Double> cfFetch = cfQuery.thenApplyAsync(new Function<String, Double>() {
            @Override
            public Double apply(String code) {
                 //System.out.println("code==>" + code);
                return fetchPrice(code,"");
            }
        });

        cfFetch.thenAccept((result)->{
            System.out.println("price======>" + result);
        });

        /**
         * 多个CompletableFuture还可以并行执行。例如，我们考虑这样的场景：
         *
         * 同时从新浪和网易查询证券代码，只要任意一个返回结果，就进行下一步查询价格，
         * 查询价格也同时从新浪和网易查询，只要任意一个返回结果，就完成操作：
         */

        CompletableFuture<String> cfQueryFromSina =
                CompletableFuture.supplyAsync(()-> queryCode("china gas","http://www.sina.com"));

        CompletableFuture<String> cfQueryFromBaidu =
                CompletableFuture.supplyAsync(()->queryCode("china gas","http://www.baidu.com"));


        //用anyOf合并为一个新的CompletableFuture
        CompletableFuture<Object> cfQuery1 = CompletableFuture.anyOf(cfQueryFromSina,cfQueryFromBaidu);

        //两个CompletableFuture执行异步查询

        CompletableFuture<Double> cfFetchFromSina = cfQuery.thenApplyAsync((code)->{
            return fetchPrice(code,"sina");
        });

        CompletableFuture<Double> cfFetchFromBaidu = cfQuery.thenApplyAsync((code)->{
            return fetchPrice(code,"baidu");
        });

        //用anyOf合并为一个新的CompletableFuture

        CompletableFuture<Object> cfFetch1 = CompletableFuture.anyOf(cfFetchFromSina,cfFetchFromBaidu);
        //最终结果
        cfFetch1.thenAccept((result)->{
            System.out.println("result==>" + result);
        });







        // 主线程不要立刻结束，否则CompletableFuture默认使用的线程池会立刻关闭:
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static String queryCode(String name,String url) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if(url.contains("sina")){
            return "601857";
        }else{
            return "200000";
        }

    }

    private static Double fetchPrice(String code , String url) {
//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        if(Math.random()<0.3){
//            throw new RuntimeException("fetch price failed");
//        }
        if(code.equals("601857")){
            return 3.1415926;
        }else{
            return 5+ Math.random()*20;
        }

    }
}
